#!/usr/bin/env node

/**
 * 全栈应用启动脚本 - 宝塔面板优化版
 * 包含数据库启动，支持三个主数据库和一个备用数据库
 */

import { execSync, spawn } from 'child_process';
import { fileURLToPath } from 'url';
import { dirname, join } from 'path';
import { existsSync, readFileSync } from 'fs';

const __filename = fileURLToPath(import.meta.url);
const __dirname = dirname(__filename);

class ApplicationStarter {
    constructor() {
        this.projectRoot = __dirname;
        this.backendDir = join(this.projectRoot, 'backend');
        this.frontendDir = join(this.projectRoot, 'frontend');
        this.userClientDir = join(this.projectRoot, 'user-client');
        this.configDir = join(this.projectRoot, 'config');
        this.scriptsDir = join(this.projectRoot, 'scripts');
        
        // 端口配置
        this.ports = {
            backend: 3000,
            frontend: 3001,
            userClient: 3002
        };
        
        this.processes = [];
        this.maxRetries = 3;
        this.retryDelay = 2000;
        
        // 数据库配置
        this.databases = {
            postgresql: { name: 'PostgreSQL', port: 5432, status: 'unknown' },
            redis: { name: 'Redis', port: 6379, status: 'unknown' },
            mongodb: { name: 'MongoDB', port: 27017, status: 'unknown' },
            sqlite: { name: 'SQLite备用', file: 'data/bike_wholesale.db', status: 'unknown' }
        };
        
        // 检查是否在宝塔面板环境
        this.isBtPanel = existsSync('/www/server/panel');
    }

    // 检查Node.js版本
    checkNodeVersion() {
        console.log('🔍 检查Node.js版本...');
        const nodeVersion = process.version;
        const majorVersion = parseInt(nodeVersion.slice(1).split('.')[0]);
        
        if (majorVersion < 18) {
            console.error('❌ Node.js版本过低，需要 >= 18.0.0');
            console.log('💡 请升级Node.js: https://nodejs.org/');
            process.exit(1);
        }
        
        console.log(`✅ Node.js版本: ${nodeVersion}`);
    }

    // 检查依赖是否已安装
    checkDependencies() {
        console.log('\n📦 检查项目依赖...');
        
        const packageFiles = [
            { path: join(this.projectRoot, 'package.json'), dir: this.projectRoot },
            { path: join(this.backendDir, 'package.json'), dir: this.backendDir },
            { path: join(this.frontendDir, 'package.json'), dir: this.frontendDir },
            { path: join(this.userClientDir, 'package.json'), dir: this.userClientDir }
        ];

        for (const pkg of packageFiles) {
            if (existsSync(pkg.path)) {
                const pkgContent = JSON.parse(readFileSync(pkg.path, 'utf8'));
                const nodeModulesDir = join(pkg.dir, 'node_modules');
                
                if (!existsSync(nodeModulesDir)) {
                    console.log(`📥 安装依赖: ${pkgContent.name}`);
                    try {
                        execSync('npm install', { 
                            cwd: pkg.dir, 
                            stdio: 'inherit',
                            timeout: 180000 // 3分钟超时
                        });
                        console.log(`✅ ${pkgContent.name} 依赖安装完成`);
                    } catch (error) {
                        console.error(`❌ ${pkgContent.name} 依赖安装失败:`, error.message);
                        console.log('💡 尝试使用: npm install --force');
                        try {
                            execSync('npm install --force', { 
                                cwd: pkg.dir, 
                                stdio: 'inherit',
                                timeout: 180000
                            });
                            console.log(`✅ ${pkgContent.name} 依赖强制安装完成`);
                        } catch (forceError) {
                            console.error(`💥 ${pkgContent.name} 依赖安装彻底失败，请手动检查`);
                        }
                    }
                } else {
                    console.log(`✅ ${pkgContent.name} 依赖已安装`);
                }
            }
        }
    }

    // 启动数据库服务
    async startDatabases() {
        console.log('\n🗄️ 启动数据库服务...');
        
        if (this.isBtPanel) {
            console.log('🔧 宝塔面板环境检测到，使用系统服务启动数据库');
        } else {
            console.log('💻 普通Linux环境，请确保数据库服务已安装并启动');
        }
        
        try {
            // 运行数据库启动脚本
            const dbStartScript = join(this.scriptsDir, 'start-databases.sh');
            if (existsSync(dbStartScript)) {
                console.log('🚀 执行数据库启动脚本...');
                execSync(`chmod +x ${dbStartScript} && ${dbStartScript}`, {
                    stdio: 'inherit',
                    cwd: this.projectRoot,
                    timeout: 60000 // 60秒超时
                });
            } else {
                console.log('💡 数据库启动脚本不存在，跳过数据库启动');
            }
            
            // 初始化SQLite备用数据库
            await this.initSQLiteDatabase();
            
            console.log('✅ 数据库服务启动完成');
            
        } catch (error) {
            console.warn('⚠️ 数据库启动失败，使用备用方案:', error.message);
            console.log('💡 应用将使用SQLite备用数据库和内存缓存');
        }
    }

    // 初始化SQLite备用数据库
    async initSQLiteDatabase() {
        console.log('💾 初始化SQLite备用数据库...');
        
        try {
            const initScript = join(this.scriptsDir, 'init-sqlite.js');
            if (existsSync(initScript)) {
                execSync(`node ${initScript}`, {
                    stdio: 'inherit',
                    cwd: this.projectRoot,
                    timeout: 30000 // 30秒超时
                });
                console.log('✅ SQLite备用数据库初始化完成');
            } else {
                console.log('💡 SQLite初始化脚本不存在，跳过初始化');
            }
        } catch (error) {
            console.warn('⚠️ SQLite数据库初始化失败:', error.message);
        }
    }

    // 检查数据库服务状态
    async checkDatabaseStatus() {
        console.log('\n🔍 检查数据库服务状态...');
        
        // PostgreSQL状态
        try {
            if (this.isBtPanel) {
                const status = execSync('systemctl is-active postgresql', { stdio: 'pipe', encoding: 'utf8' }).trim();
                this.databases.postgresql.status = status;
            } else {
                const pgProcess = execSync('pgrep -x postgres', { stdio: 'pipe' }).toString().trim();
                this.databases.postgresql.status = pgProcess ? 'active' : 'inactive';
            }
        } catch {
            this.databases.postgresql.status = 'inactive';
        }
        
        // Redis状态
        try {
            if (this.isBtPanel) {
                const status = execSync('systemctl is-active redis', { stdio: 'pipe', encoding: 'utf8' }).trim();
                this.databases.redis.status = status;
            } else {
                const redisProcess = execSync('pgrep -x redis-server', { stdio: 'pipe' }).toString().trim();
                this.databases.redis.status = redisProcess ? 'active' : 'inactive';
            }
        } catch {
            this.databases.redis.status = 'inactive';
        }
        
        // MongoDB状态
        try {
            if (this.isBtPanel) {
                const status = execSync('systemctl is-active mongod', { stdio: 'pipe', encoding: 'utf8' }).trim();
                this.databases.mongodb.status = status;
            } else {
                const mongoProcess = execSync('pgrep -x mongod', { stdio: 'pipe' }).toString().trim();
                this.databases.mongodb.status = mongoProcess ? 'active' : 'inactive';
            }
        } catch {
            this.databases.mongodb.status = 'inactive';
        }
        
        // SQLite状态
        try {
            const sqliteFile = join(this.projectRoot, 'data/bike_wholesale.db');
            this.databases.sqlite.status = existsSync(sqliteFile) ? 'active' : 'inactive';
        } catch {
            this.databases.sqlite.status = 'inactive';
        }
        
        // 显示数据库状态
        console.log('📊 数据库状态报告:');
        console.log('==================');
        for (const [key, db] of Object.entries(this.databases)) {
            console.log(`${db.name}: ${db.status}`);
        }
        console.log('==================');
    }

    // 启动后端服务器
    startBackendServer() {
        console.log('\n🚀 启动后端服务器...');
        
        const backendProcess = spawn('npm', ['run', 'start:unified'], {
            cwd: this.backendDir,
            stdio: 'inherit',
            env: { ...process.env, PORT: this.ports.backend }
        });
        
        this.processes.push({
            name: '后端服务器',
            process: backendProcess,
            port: this.ports.backend
        });
        
        return this.waitForService(this.ports.backend, '后端服务器');
    }

    // 启动前端服务器
    startFrontendServer() {
        console.log('\n🌐 启动前端服务器...');
        
        const frontendProcess = spawn('npm', ['start'], {
            cwd: this.frontendDir,
            stdio: 'inherit',
            env: { ...process.env, PORT: this.ports.frontend }
        });
        
        this.processes.push({
            name: '前端服务器',
            process: frontendProcess,
            port: this.ports.frontend
        });
        
        return this.waitForService(this.ports.frontend, '前端服务器');
    }

    // 启动用户端服务器（带重试机制）
    async startUserClientServer() {
        console.log('\n👤 启动用户端服务器...');
        
        for (let attempt = 1; attempt <= this.maxRetries; attempt++) {
            try {
                console.log(`🔄 尝试 ${attempt}/${this.maxRetries} 启动用户端服务器...`);
                
                const userClientProcess = spawn('node', ['server.js'], {
                    cwd: this.userClientDir,
                    stdio: 'inherit',
                    env: { 
                        ...process.env, 
                        PORT: this.ports.userClient,
                        NODE_ENV: 'development'
                    }
                });
                
                this.processes.push({
                    name: '用户端服务器',
                    process: userClientProcess,
                    port: this.ports.userClient
                });
                
                // 等待服务器启动
                await this.waitForService(this.ports.userClient, '用户端服务器', 15000);
                console.log('✅ 用户端服务器启动成功');
                return true;
                
            } catch (error) {
                console.error(`❌ 用户端服务器启动失败 (尝试 ${attempt}/${this.maxRetries}):`, error.message);
                
                if (attempt < this.maxRetries) {
                    console.log(`⏳ 等待 ${this.retryDelay/1000} 秒后重试...`);
                    await new Promise(resolve => setTimeout(resolve, this.retryDelay));
                } else {
                    console.log('💡 用户端服务器启动失败，但其他服务将继续运行');
                    return false;
                }
            }
        }
    }

    // 等待服务启动
    waitForService(port, serviceName, timeout = 30000) {
        return new Promise((resolve, reject) => {
            const startTime = Date.now();
            const checkInterval = setInterval(() => {
                try {
                    execSync(`curl -s http://localhost:${port}/health > /dev/null`, { 
                        stdio: 'pipe' 
                    });
                    clearInterval(checkInterval);
                    console.log(`✅ ${serviceName} 启动成功 (端口: ${port})`);
                    resolve(true);
                } catch (error) {
                    if (Date.now() - startTime > timeout) {
                        clearInterval(checkInterval);
                        console.error(`❌ ${serviceName} 启动超时`);
                        reject(new Error(`${serviceName} 启动超时`));
                    }
                }
            }, 1000);
        });
    }

    // 测试数据库连接（改进版）
    async testDatabaseConnection() {
        console.log('\n🔗 测试数据库连接...');
        
        try {
            // 等待后端服务器完全启动
            await new Promise(resolve => setTimeout(resolve, 3000));
            
            // 测试后端健康检查
            const healthResponse = execSync(`curl -s http://localhost:${this.ports.backend}/health`, {
                stdio: 'pipe',
                encoding: 'utf8',
                timeout: 10000
            });
            
            const healthData = JSON.parse(healthResponse);
            console.log('✅ 后端服务器健康状态:', healthData.status);
            
            // 测试数据库连接状态
            if (healthData.database && healthData.database !== 'disconnected') {
                console.log('✅ 数据库连接状态:', healthData.database);
            } else {
                console.log('💡 数据库连接状态: 使用备用数据库或内存存储');
            }
            
            return true;
        } catch (error) {
            console.log('💡 数据库连接测试跳过，服务可能使用备用数据库或内存存储');
            console.log('💡 错误信息:', error.message);
            return false;
        }
    }

    // 显示启动信息（宝塔面板优化版）
    showStartupInfo() {
        console.log('\n🎉 全栈应用启动完成！');
        console.log('='.repeat(60));
        
        if (this.isBtPanel) {
            console.log('🏢 宝塔面板环境检测到');
            console.log('💡 建议在宝塔面板中配置反向代理和SSL证书');
        }
        
        console.log('\n📊 服务状态:');
        console.log(`   后端服务器: http://localhost:${this.ports.backend}`);
        console.log(`   前端服务器: http://localhost:${this.ports.frontend}`);
        console.log(`   用户端服务器: http://localhost:${this.ports.userClient}`);
        
        console.log('\n🔗 测试链接:');
        console.log(`   后端健康检查: http://localhost:${this.ports.backend}/health`);
        console.log(`   前端管理页面: http://localhost:${this.ports.frontend}`);
        console.log(`   用户端首页: http://localhost:${this.ports.userClient}`);
        
        console.log('\n🗄️ 数据库状态:');
        for (const [key, db] of Object.entries(this.databases)) {
            const statusIcon = db.status === 'active' ? '✅' : '❌';
            console.log(`   ${statusIcon} ${db.name}: ${db.status}`);
        }
        
        console.log('\n💡 管理命令:');
        if (this.isBtPanel) {
            console.log('   数据库管理: sudo systemctl {start|stop|restart} postgresql redis mongod');
            console.log('   服务管理: pm2 {start|stop|restart|status} all');
        } else {
            console.log('   启动所有服务: npm start');
            console.log('   单独启动后端: cd backend && npm start');
            console.log('   单独启动前端: cd frontend && npm start');
            console.log('   单独启动用户端: cd user-client && npm start');
        }
        
        console.log('\n🛑 停止服务: Ctrl+C');
        console.log('='.repeat(60));
        
        // 宝塔面板部署建议
        if (this.isBtPanel) {
            console.log('\n🔧 宝塔面板部署建议:');
            console.log('1. 在宝塔面板中创建网站');
            console.log('2. 配置反向代理到后端服务器 (端口 3000)');
            console.log('3. 配置SSL证书启用HTTPS');
            console.log('4. 在网站设置中配置伪静态规则');
            console.log('5. 使用PM2管理Node.js进程');
        }
    }

    // 处理进程退出
    setupProcessHandlers() {
        process.on('SIGINT', () => {
            console.log('\n🛑 正在停止所有服务...');
            this.processes.forEach(proc => {
                try {
                    proc.process.kill('SIGTERM');
                    console.log(`✅ ${proc.name} 已停止`);
                } catch (error) {
                    console.log(`💡 ${proc.name} 停止失败`);
                }
            });
            process.exit(0);
        });

        process.on('SIGTERM', () => {
            console.log('\n🛑 收到终止信号，正在停止服务...');
            this.processes.forEach(proc => proc.process.kill('SIGTERM'));
            process.exit(0);
        });
    }

    // 主启动方法（改进版）
    async start() {
        try {
            console.log('🚀 开始启动全栈应用...\n');
            
            // 1. 检查Node.js版本
            this.checkNodeVersion();
            
            // 2. 检查并安装依赖
            this.checkDependencies();
            
            // 3. 启动数据库服务
            await this.startDatabases();
            
            // 4. 设置进程处理器
            this.setupProcessHandlers();
            
            // 5. 按顺序启动服务器（避免端口冲突）
            console.log('🎯 按顺序启动服务器...');
            
            // 先启动后端服务器
            console.log('\n1️⃣ 启动后端服务器...');
            await this.startBackendServer();
            
            // 等待后端服务器完全启动
            await new Promise(resolve => setTimeout(resolve, 3000));
            
            // 然后启动前端服务器
            console.log('\n2️⃣ 启动前端服务器...');
            await this.startFrontendServer();
            
            // 最后启动用户端服务器（带重试机制）
            console.log('\n3️⃣ 启动用户端服务器...');
            await this.startUserClientServer();
            
            // 6. 测试数据库连接
            await this.testDatabaseConnection();
            
            // 7. 显示启动信息
            this.showStartupInfo();
            
            console.log('\n🎉 全栈应用启动完成！');
            console.log('💡 如果用户端服务器启动失败，可以单独启动: cd user-client && npm start');
            
        } catch (error) {
            console.error('💥 启动过程中发生错误:', error.message);
            console.log('💡 请检查以下可能的问题:');
            console.log('   • 端口是否被占用');
            console.log('   • 数据库服务是否运行');
            console.log('   • 依赖是否安装完整');
            console.log('💡 可以尝试单独启动服务:');
            console.log('   • 后端: cd backend && npm start');
            console.log('   • 前端: cd frontend && npm start');
            console.log('   • 用户端: cd user-client && npm start');
            process.exit(1);
        }
    }
}

// 启动应用
const starter = new ApplicationStarter();
starter.start().catch(error => {
    console.error('💥 应用启动失败:', error);
    process.exit(1);
});